001    /* EVolve - an Extensible Software Visualization Framework
002     * Copyright (C) 2001-2002 Qin Wang
003     *
004     * This library is free software; you can redistribute it and/or
005     * modify it under the terms of the GNU Library General Public
006     * License as published by the Free Software Foundation; either
007     * version 2 of the License, or (at your option) any later version.
008     *
009     * This library is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012     * Library General Public License for more details.
013     *
014     * You should have received a copy of the GNU Library General Public
015     * License along with this library; if not, write to the
016     * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017     * Boston, MA 02111-1307, USA.
018     */
019    
020    /*
021     * EVolve is distributed at http://www.sable.mcgill.ca/EVolve/
022     */
023    
024    package EVolve.data;
025    
026    import java.util.*;
027    
028    /**
029     * Element builder.
030     */
031    public abstract class ElementBuilder {
032        private static int typeCounter; // counter of element type
033    
034        private String elementName; // name of the elements
035        private String elementDescription; // description of the elements
036    
037        protected int elementType; // type of the elements
038        private ElementDefinition elementDefinition; // definition of the elements
039    
040        private ArrayList fieldDefinitionList; // field definitions
041    
042        private int entityCounter; // counter of entities
043        private String entityName; // name of the entity
044        private long[] field; // fields
045        private boolean isOptional;
046    
047        /**
048         * Creates an element builder.
049         *
050         * @param   elementName name of the elements
051         * @param   elementDescription description of the elements
052         */
053        protected ElementBuilder(String elementName, String elementDescription) {
054            this.elementName = elementName;
055            this.elementDescription = elementDescription;
056    
057            typeCounter++;
058            this.elementType = typeCounter;
059            this.elementDefinition = null;
060            this.fieldDefinitionList = new ArrayList();
061            this.entityCounter = -1;
062        }
063    
064        /**
065         * Initializes the element builders.
066         */
067        public static void init() {
068            typeCounter = -1;
069        }
070    
071        /**
072         * Builds the definition of a value field.
073         *
074         * @param   fieldName name of the field
075         * @param   fieldProperty property of the field
076         * @param   fieldDescription description of the field
077         * @return  the field definition
078         */
079        public FieldDefinition buildValueDefinition(String fieldName, String[] fieldProperty, String fieldDescription) {
080            assert(elementDefinition == null) : ("The definition of element " + elementName + " is already built, cannot add field definition to it.");
081    
082            FieldDefinition fieldDefinition = new FieldDefinition(fieldName, fieldDefinitionList.size(), -1, fieldDescription);
083            if (fieldProperty != null) {
084                for (int i = 0; i < fieldProperty.length; i++) {
085                    fieldDefinition.addProperty(fieldProperty[i]);
086                }
087            }
088            fieldDefinitionList.add(fieldDefinition);
089    
090            return fieldDefinition;
091        }
092    
093        /**
094         * Builds the definition of a reference field.
095         *
096         * @param   fieldName name of the field
097         * @param   referenceBuilder builder of the reference
098         * @param   fieldProperty property of the field
099         * @param   fieldDescription description of the field
100         * @return  the field definition
101         */
102        public FieldDefinition buildReferenceDefinition(String fieldName, EntityBuilder referenceBuilder, String[] fieldProperty, String fieldDescription) {
103            assert (elementDefinition == null) : ("The definition of element " + elementName + " is already built, cannot add field definition to it.");
104    
105            FieldDefinition fieldDefinition = new FieldDefinition(fieldName, fieldDefinitionList.size(), referenceBuilder.elementType, fieldDescription);
106            if (fieldProperty != null) {
107                for (int i = 0; i < fieldProperty.length; i++) {
108                    fieldDefinition.addProperty(fieldProperty[i]);
109                }
110            }
111            fieldDefinitionList.add(fieldDefinition);
112    
113            return fieldDefinition;
114        }
115    
116        /**
117         * Builds the element definition.
118         *
119         * @return  the element definition
120         */
121        protected EntityDefinition buildEntityDefinition() {
122            assert (elementDefinition == null) : ("The definition of element " + elementName + " is already built.");
123    
124            FieldDefinition[] fieldDefinition = new FieldDefinition[fieldDefinitionList.size()];
125            for (int i = 0; i < fieldDefinition.length; i++) {
126                fieldDefinition[i] = (FieldDefinition)(fieldDefinitionList.get(i));
127            }
128    
129            elementDefinition = new EntityDefinition(elementName, elementType, fieldDefinition, elementDescription);
130    
131            return (EntityDefinition)(elementDefinition);
132        }
133    
134        /**
135         * Builds the element definition.
136         *
137         * @return  the element definition
138         */
139        protected EventDefinition buildEventDefinition() {
140            assert (elementDefinition == null) : ("The definition of element " + elementName + " is already built.");
141    
142            FieldDefinition[] fieldDefinition = new FieldDefinition[fieldDefinitionList.size()];
143            for (int i = 0; i < fieldDefinition.length; i++) {
144                fieldDefinition[i] = (FieldDefinition)(fieldDefinitionList.get(i));
145            }
146    
147            elementDefinition = new EventDefinition(elementName, elementType, fieldDefinition, elementDescription);
148    
149            return (EventDefinition)(elementDefinition);
150        }
151    
152        /**
153         * Checks if definition is built.
154         *
155         * @return  true if definition is built
156         */
157        private boolean checkNewElement() {
158            for (int i = 0; i < field.length; i++) {
159                field[i] = Integer.MIN_VALUE;
160            }
161            return (elementDefinition != null);
162        }
163    
164        /**
165         * Starts building new entity.
166         *
167         * @param   entityName name of the entity
168         */
169        protected void newEntity(String entityName) {
170            field = new long[elementDefinition.getFieldDefinition().length];
171    
172            assert (checkNewElement()) : ("The definition of " + elementName + " must be built before building elements.");
173    
174            this.entityName = entityName;
175        }
176    
177        /**
178         * Starts building new event.
179         */
180        protected void newEvent() {
181            field = new long[elementDefinition.getFieldDefinition().length];
182            isOptional = false;
183    
184            assert (checkNewElement()) : ("The definition of " + elementName + " must be built before building elements.");
185        }
186    
187        /**
188         * Starts building new event.
189         * @param    isOptional    indicate whether this event is an optional event
190         */
191        protected void newEvent(boolean isOptional) {
192            newEvent();
193            this.isOptional = isOptional;
194    
195            assert (checkNewElement()) : ("The definition of " + elementName + " must be built before building elements.");
196        }
197    
198        /**
199         * Adds a value field.
200         *
201         * @param   key key of the field
202         * @param   value value of the field
203         */
204        public void addValueField(FieldDefinition fieldKey, long value) {
205            assert (elementDefinition != null) : ("The definition of " + elementName + " must be built before building elements.");
206            assert (elementDefinition.getFieldDefinition()[fieldKey.getIndex()].getReference() == -1) : ("Wrong field type, " + fieldKey.getName() + " should be a reference.");
207            assert (field[fieldKey.getIndex()] == Integer.MIN_VALUE) : (fieldKey.getName() + "is already added.");
208    
209            field[fieldKey.getIndex()] = value;
210        }
211    
212        /**
213         * Adds a reference field.
214         *
215         * @param   key key of the field
216         * @param   reference the reference
217         */
218        public void addReferenceField(FieldDefinition fieldKey, Entity reference) {
219            assert (elementDefinition != null) : ("The definition of " + elementName + " must be built before building elements.");
220            assert (elementDefinition.getFieldDefinition()[fieldKey.getIndex()].getReference() != -1) : ("Wrong field type, " + fieldKey.getName() + " should be a value.");
221            assert (elementDefinition.getFieldDefinition()[fieldKey.getIndex()].getReference() == reference.getType()) : ("Wrong entity type.");
222            assert (field[fieldKey.getIndex()] == Integer.MIN_VALUE) : (fieldKey.getName() + "is already added.");
223    
224            //try {
225            field[fieldKey.getIndex()] = reference.getId();
226            /*} catch (Exception e) {
227                int i=0;
228                i++;
229            } */
230        }
231    
232        /**
233         * Checks if all fields are added.
234         *
235         * @return  true if all fields are added
236         */
237        private boolean checkBuildElement() {
238            boolean returnVal = true;
239            for (int i = 0; i < field.length -1; i++) {
240                if (field[i] == Integer.MIN_VALUE) {
241                    returnVal = false;
242                    break;
243                }
244            }
245            return returnVal;
246        }
247    
248        /**
249         * Builds the entity.
250         *
251         * @return  the entity
252         */
253        protected Entity buildEntity() {
254            assert (elementDefinition != null) : ("The definition of " + elementName + " must be built before building elements.");
255            assert (checkBuildElement()) : ("Wrong field number.");
256    
257            entityCounter++;
258            return new Entity(elementDefinition.getType(), entityCounter, entityName, field);
259        }
260    
261        /**
262         * Builds the event.
263         *
264         * @return  the event
265         */
266        protected Event buildEvent() {
267            assert (elementDefinition != null) : ("The definition of " + elementName + " must be built before building elements.");
268            assert (checkBuildElement()) : ("Wrong field number.");
269    
270            return new Event(elementDefinition.getType(), field, isOptional);
271        }
272    
273    
274    }